/**
 * 
 */
package org.youisoft.summer.evaluator.function.core;

import org.youisoft.summer.evaluator.InvokeException;
import org.youisoft.summer.evaluator.context.CalContext;
import org.youisoft.summer.evaluator.function.AbstractFunction;
import org.youisoft.summer.evaluator.operator.Operator;
import org.youisoft.summer.evaluator.operator.base.ClassOperator;
import org.youisoft.summer.evaluator.operator.base.MapOperator;
import org.youisoft.summer.evaluator.operator.base.ObjectOperator;
import org.youisoft.summer.evaluator.operator.base.StringOperator;

/**
 * @author zijiang.jl
 *
 */
public class RegisterFunction extends AbstractFunction{

	
	private static final java.util.List<Class<?>> supports;
	static{
		supports=new java.util.ArrayList<Class<?>>();
		supports.add(ClassOperator.class);
		supports.add(MapOperator.class);
	}

	@Override
	protected boolean checkOperator(int index, Operator<?> operator) {
		return supports.contains(operator.getClass());
	}

	
	@Override
	public <C,R,P> Operator<?> doInvoke(CalContext<C,R,P> context,Operator<?>... operator) throws InvokeException{
		java.util.Map<Operator<?>, Operator<?>> map;
		for(int i=0;i<operator.length;i++){
			if(ClassOperator.class.isAssignableFrom(operator[i].getClass())){
				try {
					this.register(ClassOperator.class.cast(operator[i]).value().newInstance());
				}catch (Exception e) {
					logger.error("register function failure:"+operator[i].getClass().getName());

				}
			}else if(MapOperator.class.isAssignableFrom(operator[i].getClass())){
				@SuppressWarnings("unchecked")
				MapOperator<Operator<?>> mo=MapOperator.class.cast(operator[i]);
				map=mo.value();
				for(java.util.Iterator<Operator<?>> it=map.keySet().iterator();it.hasNext();){
					Operator<?> key=it.next();
					Operator<?> value=map.get(key);
					if(StringOperator.class.isAssignableFrom(key.getClass())){
						StringOperator so=StringOperator.class.cast(key);
						if(ObjectOperator.class.isAssignableFrom(value.getClass())){
							ObjectOperator<?> oo=ObjectOperator.class.cast(value);
							this.register(so.value(), oo.value());	
						}else if(ClassOperator.class.isAssignableFrom(value.getClass())){
							try {
								this.register(so.value(),ClassOperator.class.cast(value).value().newInstance());
							}catch (Exception e) {
								logger.error("register function failure:"+operator[i].getClass().getName());

							}
							
						}

					}
				}
			}

		}
		return Operator.nullInstance;
	}
}
